/***************************************************
* @版权：哈尔滨工业大学自动化测试与控制研究所
* @文件名：HITATCI_PCM.c
* @作者：Liu Yanku
* @版本：V1.0
* @时间：2023-4-13
* @功能描述：接收产品PCM码流数据
* @修改日志：
***************************************************/

//本库使用的头文件
#include "lib_hitmc_pxie_opt.h"
#include "libStandard_pxie.h" 

/* 
 * @函数名：	HITATCI_PXIe_init
 * @描述：		初始化PXIe模块，获取仪器句柄
 * @输入参数1：	ResourceName		-	仪器的逻辑地址
 * @输入参数2：	IdQuery  	 		-	TRUE：进行仪器识别
										FALSE：不进行仪器识别
 * @输入参数3：	Reset 				-	TRUE：复位仪器
										FALSE：不复位仪器
 * @输出参数1：	viPCM				-	仪器句柄
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC HITATCI_PXIe_init (ViRsrc ResourceName, ViBoolean IdQuery, ViBoolean Reset, ViSession *viPCM)
{
    ViStatus ret = 0;

   	//打开设备
    ret = PXIe_viOpen (0, ResourceName, 0, 0, viPCM);

	// 返回函数操作结果
	return ret;
}

/*
 * @函数名：	HITATCI_PXIe_Close
 * @描述：		关闭PXIe模块，释放仪器句柄
 * @输入参数1：	vi			-	仪器句柄
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC HITATCI_PXIe_Close (ViSession vi)
{
	ViStatus ret = 0;

	// 关闭设备
    ret = PXIe_viClose(vi);

	// 返回关闭函数结果
	return ret;
}

/*
 * @函数名：	HITATCI_PXIe_viIn32_dma
 * @描述：		从FPGA读取数据
 * @输入参数1：     vi：句柄
 * @输入参数2：     vendor_id：返回设备的厂商ID
 * @输入参数3：     pci_device_id：返回设备的设备ID
 * @输入参数4：     pci_slot_id：返回设备的slot号
 * @输入参数5：     pci_bus_id：返回设备的总线号
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC  HITATCI_PXIe_viDevmsg (ViSession vi, ViPUInt16 vendor_id, ViPUInt16 pci_device_id, ViPUInt16 pci_slot_id, ViPUInt16 pci_bus_id)
{
    ViStatus ret = VI_SUCCESS;

    // 获取设备信息
    ret = PXIe_viDevmsg(vi, vendor_id, pci_device_id, pci_slot_id, pci_bus_id);

    return ret;
}

/*
 * @函数名：	HITATCI_PXIe_viIn32
 * @描述：		从FPGA的寄存器空间读取32位值
 * @输入参数1：     vi：句柄
 * @输入参数2：     space：bar空间，0,1,2,3,4,5
 * @输入参数3：     offset：偏移量
 * @输入参数4：     val32：读取的值
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC  HITATCI_PXIe_viIn32 (ViSession vi, ViUInt16 space, ViBusAddress offset, ViPUInt32 val32)
{
    ViStatus ret = VI_SUCCESS;

    // 向PXIe中写入数据
    ret = PXIe_viIn32 (vi, space, offset, val32);

    return ret;
}

/*
 * @函数名：	HITATCI_PXIe_viOut32
 * @描述：		向FPGA的寄存器空间写入32位值
 * @输入参数1：     vi：句柄
 * @输入参数2：     space：bar空间，0,1,2,3,4,5
 * @输入参数3：     offset：偏移量
 * @输入参数4：     val32：写入的值
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC  HITATCI_PXIe_viOut32 (ViSession vi, ViUInt16 space, ViBusAddress offset, ViUInt32  val32)
{
    ViStatus ret = VI_SUCCESS;

    // 从PXIe中读取数据
    ret = PXIe_viOut32 (vi, space, offset, val32);

    return ret;
}

/*
 * @函数名：	HITATCI_PXIe_viIn32_dma
 * @描述：		从FPGA读取数据
 * @输入参数1：     vi：句柄
 * @输入参数2：     space：bar空间，0,1,2,3,4,5
 * @输入参数3：     offset：偏移量
 * @输入参数4：     val32：存储读取序列的值
 * @输入参数5：     val32_len：读取的个数
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC  HITATCI_PXIe_viIn32_dma (ViSession vi, ViUInt16 space, ViBusAddress offset, ViPUInt32 val32, ViUInt32 val32_len)
{
    ViStatus ret = VI_SUCCESS;

    // 通过XDMA工具，向FPGA写入数据
    ret = PXIe_viIn32_dma (vi, space, offset, val32, val32_len);

    return ret;
}

/*
 * @函数名：	HITATCI_PXIe_viOut32_dma
 * @描述：		向FPGA写入数据
 * @输入参数1：     vi：句柄
 * @输入参数2：     space：bar空间，0,1,2,3,4,5
 * @输入参数3：     offset：偏移量
 * @输入参数4：     val32：存储读取序列的值
 * @输入参数5：     val32_len：读取的个数
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC  HITATCI_PXIe_viOut32_dma (ViSession vi, ViUInt16 space, ViBusAddress offset, ViPUInt32  val32, ViUInt32 val32_len)
{
    ViStatus ret = VI_SUCCESS;

    // 通过XDMA工具，从FPGA读取数据
    ret = PXIe_viOut32_dma (vi, space, offset, val32, val32_len);

    return ret;
}

/*
 * @函数名：	HITATCI_PXIe_self_test
 * @描述：		pxie板卡自检功能
 * @输入参数1：	vi			-	仪器句柄
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC HITATCI_PXIe_self_test (ViSession vi)
{
    ViStatus errStatus = VI_SUCCESS;

    ViUInt16 vendor_id = 0;
	ViUInt16 pci_device_id = 0;
	ViUInt16 pci_slot_id = 0;
    ViUInt16 pci_bus_id = 0;
    ViUInt32 rd_data[2], wr_data[2];

    // 获取仪器信息
    errStatus = PXIe_viDevmsg (vi, &vendor_id, &pci_device_id, &pci_slot_id, &pci_bus_id);
    printf("vendor_id :%x\n", vendor_id);
    printf("pci_device_id :%x\n", pci_device_id);
    printf("pci_slot_id :%x\n", pci_slot_id);
    printf("pci_bus_id :%x\n", pci_bus_id);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);
    printf("1 0x0 rd_data :%x\n", rd_data[0]);

    // 调整0x0地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x0, wr_data[0]);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);
    printf("2 0x0 rd_data :%x\n", rd_data[0]);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);
    printf("3 0x0 rd_data :%x\n", rd_data[0]);

    // 调整0x0地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x0, wr_data[0]);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);
    printf("4 0x0 rd_data :%x\n", rd_data[0]);

    // 测试失败
    if(rd_data[0] != wr_data[0]){
        return -1;
    }

    // 读取0x4地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x4, &rd_data[0]);
    printf("1 0x4 rd_data :%x\n", rd_data[0]);

    // 调整0x4地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x4, wr_data[0]);

    // 读取0x4地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x4, &rd_data[0]);
    printf("2 0x4 rd_data :%x\n", rd_data[0]);

    // 读取0x4地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x4, &rd_data[0]);
    printf("3 0x4 rd_data :%x\n", rd_data[0]);

    // 调整0x4地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x4, wr_data[0]);

    // 读取0x4地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x4, &rd_data[0]);
    printf("4 0x4 rd_data :%x\n", rd_data[0]);

    // 测试失败
    if(rd_data[0] != wr_data[0]){
        return -1;
    }

    // 读取0x8地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x8, &rd_data[0]);
    printf("1 0x8 rd_data :%x\n", rd_data[0]);

    // 调整0x8地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x8, wr_data[0]);

    // 读取0x8地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x8, &rd_data[0]);
    printf("2 0x8 rd_data :%x\n", rd_data[0]);

    // 读取0x8地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x8, &rd_data[0]);
    printf("3 0x8 rd_data :%x\n", rd_data[0]);

    // 调整0x8地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x8, wr_data[0]);

    // 读取0x8地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x8, &rd_data[0]);
    printf("4 0x8 rd_data :%x\n", rd_data[0]);

        // 测试失败
    if(rd_data[0] != wr_data[0]){
        return -1;
    }

	// 返回句柄
	return errStatus;
}
